package com.google.code.gaeapptest.junit;

import static org.junit.Assert.fail;

import org.junit.Test;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Transaction;

public class TransactionTests extends BaseTest implements GaeTest {
	private static String TEST_TYPE = "Transaction";

	@Test
	public void allAverage() throws Exception {
		// implemented by backend service
	}

	
	@Test
	public void all() throws Exception {
		long start = System.currentTimeMillis();
		createEntity();
		readEntity();
		readUpdateEntity();
		updateEntity();
		deleteEntity();
		long elapsed = System.currentTimeMillis() - start;
		saveResult(TEST_TYPE, elapsed, "OK");
	}

	@Test
	public void createEntity() throws Exception {
		long elapsed = -1L;
		String msg = "UNKNOWN";
		try {
			DatastoreService datastore = DatastoreServiceFactory
					.getDatastoreService();
			Entity e = new Entity("Temp");
			e.setProperty("prop", "propval");
			long start = System.currentTimeMillis();
			Transaction txn = datastore.beginTransaction();
			Key k = null;
			try {
				k = datastore.put(e);
				txn.commit();
			} finally {
				if (txn.isActive()) {
					txn.rollback();
				}
			}
			elapsed = System.currentTimeMillis() - start;
			if (k != null) {
				msg = "OK";
			} else {
				msg = "ERR key:" + k;
				elapsed = -1;
				fail("unable to create");
			}
			datastore.delete(k);// Cleanup
		} catch (Exception e) {
			msg = "Err:" + e.getMessage();
			fail("Err:" + e.getMessage());
			e.printStackTrace();
		} finally {
			saveResult(TEST_TYPE, elapsed, msg);
		}
	}

	@Test
	public void readEntity() throws Exception {
		long elapsed = -1L;
		String msg = "UNKNOWN";
		try {
			DatastoreService datastore = DatastoreServiceFactory
					.getDatastoreService();
			Entity e = new Entity("Temp");
			String p = "propVal";
			e.setProperty("prop", p);
			Key k = datastore.put(e);
			long start = System.currentTimeMillis();
			Transaction txn = datastore.beginTransaction();
			try {
				e = datastore.get(k);
				txn.commit();
			} finally {
				if (txn.isActive()) {
					txn.rollback();
				}
			}
			elapsed = System.currentTimeMillis() - start;
			if (e != null && e.getProperty("prop") != null
					&& e.getProperty("prop").equals(p)) {
				msg = "OK";
			} else {
				msg = "ERR entity:" + e;
				elapsed = -1;
				fail("unable to read");
			}
			datastore.delete(k);// Cleanup
		} catch (Exception e) {
			msg = "Err:" + e.getMessage();
			fail("Err:" + e.getMessage());
			e.printStackTrace();
		} finally {
			saveResult(TEST_TYPE, elapsed, msg);
		}
	}

	@Test
	public void updateEntity() throws Exception {
		long elapsed = -1L;
		String msg = "UNKNOWN";
		try {
			DatastoreService datastore = DatastoreServiceFactory
					.getDatastoreService();
			Entity e = new Entity("Temp");
			String p = "propVal";
			e.setProperty("prop", p);
			Key k = datastore.put(e);
			e = datastore.get(k);
			p = "newVal";
			e.setProperty("prop", p);
			long start = System.currentTimeMillis();
			Transaction txn = datastore.beginTransaction();
			try {
				k = datastore.put(e);
				txn.commit();
			} finally {
				if (txn.isActive()) {
					txn.rollback();
				}
			}
			elapsed = System.currentTimeMillis() - start;
			e = datastore.get(k);
			if (e != null && e.getProperty("prop") != null
					&& e.getProperty("prop").equals(p)) {
				msg = "OK";
			} else {
				msg = "ERR entity:" + e;
				elapsed = -1;
				fail("unable to update");
			}
			datastore.delete(k);// Cleanup
		} catch (Exception e) {
			msg = "Err:" + e.getMessage();
			fail("Err:" + e.getMessage());
			e.printStackTrace();
		} finally {
			saveResult(TEST_TYPE, elapsed, msg);
		}
	}

	@Test
	public void readUpdateEntity() throws Exception {
		long elapsed = -1L;
		String msg = "UNKNOWN";
		try {
			DatastoreService datastore = DatastoreServiceFactory
					.getDatastoreService();
			Entity e = new Entity("Temp");
			String p = "propVal";
			e.setProperty("prop", p);
			Key k = datastore.put(e);
			long start = System.currentTimeMillis();
			e = datastore.get(k);
			p = "newVal";
			e.setProperty("prop", p);
			Transaction txn = datastore.beginTransaction();
			try {
				k = datastore.put(e);
				txn.commit();
			} finally {
				if (txn.isActive()) {
					txn.rollback();
				}
			}
			elapsed = System.currentTimeMillis() - start;
			e = datastore.get(k);
			if (e != null && e.getProperty("prop") != null
					&& e.getProperty("prop").equals(p)) {
				msg = "OK";
			} else {
				msg = "ERR entity:" + e;
				elapsed = -1;
				fail("unable to update");
			}
			datastore.delete(k);// Cleanup
		} catch (Exception e) {
			msg = "Err:" + e.getMessage();
			fail("Err:" + e.getMessage());
			e.printStackTrace();
		} finally {
			saveResult(TEST_TYPE, elapsed, msg);
		}
	}

	@Test
	public void deleteEntity() throws Exception {
		long elapsed = -1L;
		String msg = "UNKNOWN";
		try {
			DatastoreService datastore = DatastoreServiceFactory
					.getDatastoreService();
			Entity e = new Entity("Temp");
			String p = "propVal";
			e.setProperty("prop", p);
			Key k = datastore.put(e);
			e = datastore.get(k);
			p = "newVal";
			e.setProperty("prop", p);
			k = datastore.put(e);
			long start = System.currentTimeMillis();
			Transaction txn = datastore.beginTransaction();
			try {
				datastore.delete(k);
				txn.commit();
			} finally {
				if (txn.isActive()) {
					txn.rollback();
				}
			}
			elapsed = System.currentTimeMillis() - start;
			try {
				e = datastore.get(k);
				elapsed = -1;
				msg = "Err: delete failed";
				fail("unable to delete");
			} catch (EntityNotFoundException ex) {
				msg = "OK";
			}
		} catch (Exception e) {
			msg = "Err:" + e.getMessage();
			fail("Err:" + e.getMessage());
			e.printStackTrace();
		} finally {
			saveResult(TEST_TYPE, elapsed, msg);
		}
	}
}
